#ifndef _J1939_H_
#define _J1939_H_

#include "stdint.h"
#include "string.h"


/* 本机地址（充电机:0x86、BMS:0xF4） */
#define J1939_LOCAL_ADDRESS                     0xF4
/* 支持并行收发、解析的数量 */
#define J1939_PACK_NUMBER                       4
/* 支持的PDU内数据最大长度 */
#define J1939_PACK_DATA_SIZE_MAX                16


/* State bytes enums */
typedef enum {
    STATE_TP_CM_IDLE = 0,

    STATE_TP_CM_RTS,
    STATE_TP_CM_RTS_WAIT,

    STATE_TP_CM_CTS,
    STATE_TP_CM_CTS_WAIT,

    STATE_TP_CM_BAM,
    STATE_TP_CM_BAM_WAIT,

    STATE_TP_CM_END_ACK,
    STATE_TP_CM_END_ACK_WAIT,

    STATE_TP_CM_ABORT,
    STATE_TP_CM_ABORT_WAIT,

    STATE_TP_DT,
    STATE_TP_DT_WAIT,
}ENUM_CONTROL_STATE_BYTES_CODES;

/* Control bytes enums */
typedef enum {
    CONTROL_BYTE_TP_CM_ABORT                        = 0xFFU,
    CONTROL_BYTE_TP_CM_BAM                          = 0x20U,
    CONTROL_BYTE_TP_CM_EndOfMsgACK                  = 0x13U,
    CONTROL_BYTE_TP_CM_CTS                          = 0x11U,
    CONTROL_BYTE_TP_CM_RTS                          = 0x10U,
    CONTROL_BYTE_ACKNOWLEDGEMENT_PGN_SUPPORTED      = 0x0U,
    CONTROL_BYTE_ACKNOWLEDGEMENT_PGN_NOT_SUPPORTED  = 0x1U,
    CONTROL_BYTE_ACKNOWLEDGEMENT_PGN_ACCESS_DENIED  = 0x2U,
    CONTROL_BYTE_ACKNOWLEDGEMENT_PGN_BUSY           = 0x3U,
}ENUM_CONTROL_BYTES_CODES;

/* PGN enums */
typedef enum {
    /* NOT  J1939 standard. If you find the correct PGN number, please do a pull request */
    PGN_ADDRESS_DELETE                              = 0x000002U,
    PGN_REQUEST                                     = 0x00EA00U,
    PGN_ACKNOWLEDGEMENT                             = 0x00E800U,
    PGN_TP_CM                                       = 0x00EC00U,
    PGN_TP_DT                                       = 0x00EB00U,
    PGN_ADDRESS_CLAIMED                             = 0x00EE00U,
    PGN_PROPRIETARY_A                               = 0x00EF00U,
    PGN_COMMANDED_ADDRESS                           = 0x00FED8U,
    PGN_DM1                                         = 0x00FECAU,
    PGN_DM2                                         = 0x00FECBU,
    PGN_DM3                                         = 0x00FECCU,
    PGN_DM14                                        = 0x00D900U,
    PGN_DM15                                        = 0x00D800U,
    PGN_DM16                                        = 0x00D700U,
    PGN_SOFTWARE_IDENTIFICATION                     = 0x00FEDAU,
    PGN_ECU_IDENTIFICATION                          = 0x00FDC5U,
    PGN_COMPONENT_IDENTIFICATION                    = 0x00FEEBU,
    PGN_GENERAL_PURPOSE_VALVE_ESTIMATED_FLOW        = 0x00C600U,
    PGN_ENGINE_HOURS_65253                          = 0x00FE3FU,
    PGN_ENGINE_TEMPERATURE_1_65262                  = 0x00FEEEU,
    PGN_VEHICLE_ELECTRICAL_POWER_1_65271            = 0x00FEF7U,
    PGN_ELECTRONIC_ENGINE_CONTROLLER_1_61444        = 0x00F004U,
    PGN_COLD_START_AIDS_64966                       = 0x00FDC6U,
    PGN_FUEL_CONSUMPTION_65257                      = 0x00FEE9U,
    PGN_FUEL_ECONOMY_65266                          = 0x00FEF2U,
    PGN_ENGINE_FLUIDS_LEVEL_PRESSURE_1_65263        = 0x00FEEFU,
    PGN_ELECTRONIC_ENGINE_CONTROLLER_2_61443        = 0x00F003U,
    PGN_AMBIENT_CONDITIONS_65269                    = 0x00FEF5U,
    PGN_ENGINE_FUEL_LUBE_SYSTEMS_65130              = 0x00FE6AU,
    PGN_AUXILIARY_ANALOG_INFORMATION_65164          = 0x00FE8CU,
    PGN_AFTERTREATMENT_1_DEF_TANK_1_65110           = 0x00FE56U,
    PGN_SHUTDOWN_65252                              = 0x00FEE4U,
    PGN_ELECTRONIC_ENGINE_CONTROLLER_3_65247        = 0x00FEDFU,
    PGN_ENGINE_FLUIDS_LEVEL_PRESSURE_12_64735       = 0x00FCDFU,
    PGN_INTAKE_MANIFOLD_INFO_1_65190                = 0x00FEA6U,
    PGN_DASH_DISPLAY_65276                          = 0x00FEFCU,
    PGN_DIRECT_LAMP_CONTROL_COMMAND_1_64775         = 0x00FD07U,
    PGN_TORQUE_SPEED_CONTROL_1_0                    = 0x000000U,
    PGN_ELECTRONIC_BRAKE_CONTROLLER_1_61441         = 0x00F001U,
}ENUM_PGN_CODES;


/* PDU 结构 */
typedef struct
{
    uint8_t P   : 3;                                /* 优先级 */

    /* PGN 部分 */
    uint8_t R   : 1;                                /* 预留，必须为0 */
    uint8_t DP  : 1;                                /* Data Page(数据页) */
    uint8_t PF;                                     /* PDU Format(普通组:0x00-0xEF、拓展组:0xF0-0xFF) */
    uint8_t PS;                                     /* PDU Specific(PF=普通组:Destination Address、PF=拓展组:Group Extension) */

    uint8_t SA;                                     /* Source Address(源/目标地址) */
    uint8_t length;                                 /* 数据长度 */
    uint8_t datas[8];                               /* 数据 */
}J1939PduType;

/* TP.DT 结构 */
typedef struct
{
    uint32_t P   : 3;                               /* 优先级 */
    uint32_t PGN : 24;
    uint8_t SA;                                     /* Source Address(源/目标地址) */
    uint8_t length;                                 /* 数据长度 */
    uint8_t datas[J1939_PACK_DATA_SIZE_MAX];        /* 数据 */

    uint8_t frameNo;                                /* 当前第n个帧 */
    uint8_t frameRequestNum;                        /* 请求的剩余帧数量 */
    uint8_t state;
}J1939PackType;

/* PGN处理函数 结构 */
typedef struct
{
    uint32_t PGN;
    int8_t (* fuction)(void *pvHandle, int8_t cMode);   /* 回调函数 */

    void *next;
}J1939Fuction;


/* 支持并行收发、解析的句柄 */
extern J1939PackType g_typeJ1939Packs[J1939_PACK_NUMBER];


/* PGN 注册 */
int8_t cJ1939PgnCreat(uint32_t uiPGN, void *pvFuction);
/* PGN 主动发送 */
int8_t cJ1939PgnSend(uint32_t uiPGN, uint8_t ucDA);
/* PDU 被动接收 */
int8_t cJ1939PduReceive(J1939PackType *ptypeJ1939Pack, J1939PduType *ptypeJ1939Pdu);


/* 需要用户实现的平台处理函数 */
void *pvJ1939Malloc(uint32_t uiSize);
void vJ1939Free(void *pvMem);
int8_t cJ1939PduSend(J1939PduType *ptypeJ1939Pdu);


#endif
